#include "stat_analyze.h"
#include "stat_analyze_1.h"

Stat_Analyze::Stat_Analyze() {
	ast=AST::getInstance();
	symtab=Symtab::getInstance();
	_stack=new int(255);
	_stackpointer=0;

	_status_stack=new int(255);
	_status_stack_pointer=0;

	_node_stack=new Node*[255];
	for (int i=0;i<255;i++) 
		_node_stack[i]=Node::createNode();
	_node_stack_pointer=0;
	
	c_status=0;
	c_depth=0;
	auto_scope=-1;	

}


#define STAT_BEGIN        0   // oringal state
#define STAT_BLOCK_START  1   // {
#define STAT_BLOCK_END    2   // }

#define STAT_DEFINE       3
#define STAT_DEFINE_1     5
#define STAT_DEFINE_2     4
#define STAT_DEFINE_3     6

#define STAT_FUN_ARG_DEFINE_1   8
#define STAT_FUN_ARG_DEFINE_2   9
#define STAT_FUN_DEF_FINAL      10

#define STAT_EXP         30
#define STAT_EXP_1		 32
#define STAT_EXP_2		 31

int Stat_Analyze::gettoken(int token,char* t_name) {

L(STAT_BEGIN)
	if (token==TOKEN_BEGIN) {
		auto_scope=-1;
		c_depth++;
		return 1;
	}
	/* AUTO_SCOPE_CODE! */
	if (auto_scope==1) {
		c_depth--;
		auto_scope=-1;
	}
	if (auto_scope==2) {
		c_depth++;
		auto_scope=1;
	}

	if (token==TOKEN_INT_TYPE) {
		PUSH(token);
		GOTO(STAT_DEFINE);
		return 1;
	}
	if (token==TOKEN_DOUBLE_TYPE) {
		PUSH(token);
		GOTO(STAT_DEFINE);
		return 1;
	}
	if (token==TOKEN_CHAR_TYPE) {
		PUSH(token);
		GOTO(STAT_DEFINE);
		return 1;
	}
	if (token==TOKEN_BYTE_TYPE) {
		PUSH(token);
		GOTO(STAT_DEFINE);
		return 1;
	}
	if (token==TOKEN_SEMI) {
		GOTO(STAT_BEGIN);
		return 1;
	}

	if (token==TOKEN_END) {
		c_depth--;
		return 1;
	}
L_END


L(STAT_DEFINE)
		if (token==TOKEN_VAR) {
		int _token=POP();
		Node* _node=Node::createNode();
		_node->depth=c_depth;
		c_node=_node;
		c_node->value=VALUE_VAR_DEF;
		c_node->token=_token;
		c_node->add_arg(token,t_name);
		ast->currentNode->leftpointer=c_node;
		ast->currentNode=c_node;
		GOTO(STAT_DEFINE_2)
		return 1;
	}
L_END


L(STAT_DEFINE_1)
		if (token==TOKEN_VAR) {
		c_node->add_arg(token,t_name);
		GOTO(STAT_DEFINE_3)
		return 1;
	}
L_END

L(STAT_DEFINE_3)
	if (token==TOKEN_SEMI) {
		GOTO(STAT_BEGIN);
		return 1;
	}
	if (token==TOKEN_COMMA) {
		GOTO(STAT_DEFINE_1);
		return 1;
	}
	if (token==TOKEN_EQ) {
		c_node->add_arg(TOKEN_REF,t_name);
		GOTO(STAT_DEFINE_1);
		N_PUSH();
		GOTO(STAT_EXP)
		return 1;
	}
L_END

L(STAT_DEFINE_2)
	if (token==TOKEN_SEMI) {
		GOTO(STAT_BEGIN);
		return 1;
	}
	if (token==TOKEN_COMMA) {
		GOTO(STAT_DEFINE_1);
		return 1;
	}
	if (token==TOKEN_LPAREN) {
		c_node->value=VALUE_FUN_DEF;
		GOTO(STAT_FUN_ARG_DEFINE_1);
		return 1;
	}
	if (token==TOKEN_EQ) {
		c_node->add_arg(TOKEN_REF,t_name);
		GOTO(STAT_DEFINE_1);
		N_PUSH();
		GOTO(STAT_EXP)
		return 1;
	}
L_END

L(STAT_FUN_ARG_DEFINE_2)
	if (token==TOKEN_VAR) {
		int _token=POP();
		c_node->add_arg(_token,t_name);
		GOTO(STAT_FUN_DEF_FINAL);
		return 1;
	}
L_END

L(STAT_FUN_DEF_FINAL) 
	if (token==TOKEN_COMMA) {
		GOTO(STAT_FUN_ARG_DEFINE_1);
		return 1;
	}
	if (token==TOKEN_RPAREN) {
		auto_scope=2;
		GOTO(STAT_BEGIN);
		return 1;
	}
L_END

L(STAT_FUN_ARG_DEFINE_1)
	if (token==TOKEN_INT_TYPE) {
		PUSH(token);
		GOTO(STAT_FUN_ARG_DEFINE_2);
		return 1;
	}
	if (token==TOKEN_DOUBLE_TYPE) {
		PUSH(token);
		GOTO(STAT_FUN_ARG_DEFINE_2);
		return 1;
	}
	if (token==TOKEN_BYTE_TYPE) {
		PUSH(token);
		GOTO(STAT_FUN_ARG_DEFINE_2);
		return 1;
	}
	if (token==TOKEN_CHAR_TYPE) {
		PUSH(token);
		GOTO(STAT_FUN_ARG_DEFINE_2);
		return 1;
	}
	if (token==TOKEN_RPAREN) {
		auto_scope=2;
		GOTO(STAT_BEGIN);
		return 1;
	}
	if (token==TOKEN_VAR) {
//		GOTO(STAT_FUN_CAL);
		return 1;
	}
L_END



/////////////////////////////////
// TAG for STAT_EXP            //
/////////////////////////////////

L(STAT_EXP)
	if (token==TOKEN_VAR || token==TOKEN_NUM) {
		Node* _node=Node::createNode();
		_node->value=VALUE_EXP;
		_node->add_arg(token,t_name);
		_node->depth=c_depth;
		_node->token=TOKEN_REF;
		LPOINT(c_node);
		c_node->rightpointer=_node;
		c_node=_node;
		GOTO(STAT_EXP_2);
		return 1;
	}
	if (token==TOKEN_INC) {
		Node* _node=Node::createNode();
		_node->value=VALUE_EXP;
		_node->add_arg(token,t_name);
		_node->depth=c_depth;
		_node->token=TOKEN_REF;
		LPOINT(c_node);
		c_node->rightpointer=_node;
		c_node=_node;
		GOTO(STAT_EXP_1);
		return 1;
	}
L_END

L(STAT_EXP_1)
	if (token==TOKEN_INC) {
		c_node->add_arg(token,t_name);
		GOTO(STAT_EXP_1);
		return 1;
	}
	if (token==TOKEN_VAR || token==TOKEN_NUM) {
		c_node->add_arg(token,t_name);
		GOTO(STAT_EXP_2);
		return 1;
	}
L_END

L(STAT_EXP_2)
	if (token==TOKEN_PLUS || token==TOKEN_STAR || token==TOKEN_LPAREN || token==TOKEN_RPAREN || token==TOKEN_MUL) {
		c_node->add_arg(token,t_name);
		GOTO(STAT_EXP_1);
		return 1;
	}
	if (token==TOKEN_SEMI) {
		N_POP();
		GOTO(STAT_BEGIN);
		return 1;
	}
	if (token==TOKEN_COMMA) {
		N_POP();
		return 1;
	}
L_END



// ERROR MODULE
L(STAT_ERROR)
	GOTO(STAT_BEGIN);
	return 0;
L_END
	return 1;
}